package com.lijianlove.keeplearning.retry.guava;

import com.github.rholder.retry.*;
import com.google.common.base.Predicates;
import com.lijianlove.keeplearning.retry.guava.listener.RetryListener;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author lijian
 * @date 2019/4/28 下午5:10
 * @See https://github.com/lowzj/java-retrying
 * @see https://www.cnblogs.com/jianzh5/p/6651799.html
 */
@Slf4j
//@Service
public class RetryService {
    /**
     * 任务具体操作
     */
    private static Callable<Boolean> doTask() {
        Callable updateReimAgentsCall = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                if (1 == 1) {
                    throw new RuntimeException("xxxx");
                }
                if (1 == 1) {
                    return true;
                }
                return false;
            }
        };
        return updateReimAgentsCall;
    }

    public static void retry() {
        Retryer<Boolean> retryer = RetryerBuilder
                .<Boolean>newBuilder()
                //抛出runtime异常、checked异常时都会重试，但是抛出error不会重试。
                .retryIfException()
                //返回false也需要重试
                .retryIfResult(Predicates.equalTo(false))
//                .retryIfExceptionOfType(Error.class)// 只在抛出error重试
//                .retryIfExceptionOfType(IllegalStateException.class)
//                .retryIfExceptionOfType(NullPointerException.class)
                // 发生回调的时候的监听
                .withRetryListener(new RetryListener())
                //重调策略
                .withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS))
//                WaitStrategy：等待时长策略（控制时间间隔），返回结果为下次执行时长：
//                FixedWaitStrategy：固定等待时长策略；
//                RandomWaitStrategy：随机等待时长策略（可以提供一个最小和最大时长，等待时长为其区间随机值）
//                IncrementingWaitStrategy：递增等待时长策略（提供一个初始值和步长，等待时间随重试次数增加而增加）
//                ExponentialWaitStrategy：指数等待时长策略；
//                FibonacciWaitStrategy ：Fibonacci 等待时长策略；
//                ExceptionWaitStrategy ：异常时长等待策略；
//                CompositeWaitStrategy ：复合时长等待策略；
                //尝试次数
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();

        try {
            retryer.call(doTask());
            log.info("end...");
        } catch (ExecutionException e) {
            log.error("ExecutionException", e);
        } catch (RetryException e) {
            log.error("RetryException ", e);
        }
    }

    public static void main(String[] args) {
        retry();
    }
}
